home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-09-17 | 7.7 KB | 257 lines | [TEXT/MPS ] |
- //========================================================================================
- //
- // File: SLCySink.cpp
- // Release Version: $ ODF 2 $
- //
- // Copyright: (c) 1993 - 1996 by Apple Computer, Inc., all rights reserved.
- //
- //========================================================================================
-
- #ifndef SOM_FW_OCyberSink_xih
- #define SOM_Module_slcysink_Source
- #include <SLCySink.xih>
- #endif
-
- #ifndef FWCYSTRM_H
- #include "FWCyStrm.h"
- #endif
-
- #ifndef FWSOMENV_H
- #include "FWSOMEnv.h"
- #endif
-
- //
- // Cyberdog
- //
-
- #ifndef SOM_CyberStream_xh
- #include <CyberStream.xh>
- #endif
-
- //========================================================================================
- // SOM Utilities
- //========================================================================================
- #pragma mark SOM Utilities
-
- /*
- Since we have a SOM interface, we have to make sure we don't try to
- throw any C++ exceptions out of here; we need to catch them and convert
- them into SOM exceptions.
- */
-
- static const char FW_kInvalidException[] = "Unknown Exception!";
-
- #define FW_SOM_CALLBACK_TRY \
- FW_TRY \
- {
-
- #define FW_SOM_CALLBACK_ENDTRY \
- } \
- FW_CATCH_BEGIN \
- FW_CATCH_REFERENCE(FW_XException, exception)\
- { \
- FW_SetException(ev, exception);\
- } \
- FW_CATCH_EVERYTHING() \
- { \
- FW_DEBUG_MESSAGE(FW_kInvalidException);\
- FW_SetEvError(ev, kODErrUndefined);\
- } \
- FW_CATCH_END
-
- #pragma mark -
-
-
- //-----------------------------------------------------------------------------
- // Utilities
- //-----------------------------------------------------------------------------
-
- #define FW_YET_ANOTHER_MIN(X,Y) (((X) < (Y)) ? (X) : (Y))
-
- //-----------------------------------------------------------------------------
- // FW_GetAvailableBytes
- //-----------------------------------------------------------------------------
-
- static long FW_GetAvailableBytes (Environment *ev,
- CyberStream*& fStream, Ptr& fBuffer, Size& fRead, Size& fSize)
- {
- // Return how much data is available for reading.
- //
- // The result will be: size of buffer, if one is available, or 0.
- // The number returned may be smaller than the true value (because
- // there may be multiple buffers available).
- //
- // You will generally only use this if you are reading unstructured data,
- // and just want the data that is sitting in the network buffer so you can
- // read it and process it right away.
-
- // If we don't have a buffer, try to get a new one. We will release a buffer
- // if it is empty.
-
- if (fBuffer && (fSize-fRead) == 0) {
- fStream->ReleaseBuffer (ev, fBuffer);
- fBuffer = kODNULL;
- }
-
- check_buffer:
- if (!fBuffer) {
- short status = fStream->GetStreamStatus (ev);
- if (status & kCDDataAvailable) {
- fStream->GetBuffer (ev, &fBuffer, &fSize);
- fRead = 0;
- }
-
- // If we still have no buffer (and the connection is Ok) try to go to sleep.
- short done = status & (kCDErrorOccurred | kCDDownloadComplete | kCDAbortComplete);
- if (!fBuffer && !done) {
- #ifdef FW_DEBUG
- ThreadID current;
- FW_FailOnError (::GetCurrentThread (¤t));
- // (1) Performing lengthy network activity during the main thread is rude.
- // (2) Yielding from the main thread probably won't work anyway, because you won't
- // have a second thread to yield *to*.
- FW_ASSERT (("You should not block the main (user interface) thread!", current != kApplicationThreadID));
- #endif
- FW_FailOnError (::YieldToAnyThread());
- goto check_buffer;
- }
- }
-
- return fBuffer ? (fSize-fRead) : 0;
- }
-
- static void FW_Read (Environment *ev, void* destination, long bytes,
- CyberStream*& fStream, Ptr& fBuffer, Size& fRead, Size& fSize)
- {
- // Reads data from a CyberStream, sleeping as necessary.
- // This is a blocking synchronous call. If all the data requested is not
- // available, will sleep. If all the data can not be read, will throw an
- // exception. If you want to read *up to* X bytes, call
- // FW_GetAvailableBytes first, and call FW_Read (max (available, X)).
-
- char* buffer = (char*) destination;
-
- while (0 < bytes) {
- long available = FW_GetAvailableBytes (ev, fStream, fBuffer, fRead, fSize);
- long toRead = FW_YET_ANOTHER_MIN (available, bytes);
- if (toRead == 0)
- FW_Failure (FW_xReadableStream);
- memcpy (buffer, fBuffer + fRead, toRead);
- fRead += toRead;
- bytes -= toRead;
- buffer += toRead;
- }
- }
-
- #pragma mark -
- //-----------------------------------------------------------------------------
- // Class FW_OCyberSink (SOM)
- //-----------------------------------------------------------------------------
- #pragma mark Class FW_OCyberSink (SOM)
-
- //-----------------------------------------------------------------------------
- // SLCySink::somUninit
- //-----------------------------------------------------------------------------
-
- SOM_Scope void SOMLINK SLCySink__somUninit(FW_OCyberSink *somSelf)
- {
- FW_SOMEnvironment ev;
- FW_OCyberSinkData *somThis = FW_OCyberSinkGetData(somSelf);
-
- if (somThis->fStream) {
- // Release any empty buffer we may have.
- if (somThis->fBuffer) {
- somThis->fStream->ReleaseBuffer (ev, somThis->fBuffer);
- somThis->fBuffer = kODNULL;
- }
- // Do we need to abort the stream before deleting it?
- short status = somThis->fStream->GetStreamStatus(ev);
- if (!(status & FW_kCyberStreamDone)) {
- somThis->fStream->Abort (ev);
- do {
- ::SystemTask();
- status = somThis->fStream->GetStreamStatus(ev);
- }
- while (!(status & FW_kCyberStreamDone));
- }
- delete somThis->fStream;
- }
-
- FW_OCyberSink_parent_FW_OSink_somUninit(somSelf);
- }
-
- //-----------------------------------------------------------------------------
- // SLCySink::GetReadableBytes
- //-----------------------------------------------------------------------------
-
- SOM_Scope long SOMLINK SLCySink__GetReadableBytes(FW_OCyberSink *somSelf, Environment *ev)
- {
- long available = 0;
- FW_OCyberSinkData* somThis = FW_OCyberSinkGetData(somSelf);
-
- FW_SOM_CALLBACK_TRY
- available = FW_GetAvailableBytes (ev, somThis->fStream, somThis->fBuffer, somThis->fRead, somThis->fSize);
- FW_SOM_CALLBACK_ENDTRY
-
- return available;
- }
-
- //-----------------------------------------------------------------------------
- // SLCySink::Read
- //-----------------------------------------------------------------------------
-
- SOM_Scope void SOMLINK SLCySink__Read(FW_OCyberSink* somSelf, Environment* ev,
- void* destination,
- long count)
- {
- FW_OCyberSinkData* somThis = FW_OCyberSinkGetData(somSelf);
-
- FW_SOM_CALLBACK_TRY
- FW_Read (ev, destination, count, somThis->fStream, somThis->fBuffer, somThis->fRead, somThis->fSize);
- FW_SOM_CALLBACK_ENDTRY
- }
-
- //-----------------------------------------------------------------------------
- // SLCySink::GetWritableBytes
- //-----------------------------------------------------------------------------
-
- SOM_Scope long SOMLINK SLCySink__GetWritableBytes(FW_OCyberSink* somSelf, Environment* ev)
- {
- FW_UNUSED (somSelf);
- FW_UNUSED (ev);
-
- FW_ASSERT (("CyberStream sinks are read-only.", false));
- return 0;
- }
-
- //-----------------------------------------------------------------------------
- // SLCySink::Write
- //-----------------------------------------------------------------------------
-
- SOM_Scope void SOMLINK SLCySink__Write(FW_OCyberSink* somSelf, Environment* ev,
- void* source,
- long count)
- {
- FW_UNUSED (somSelf);
- FW_UNUSED (ev);
- FW_UNUSED (source);
- FW_UNUSED (count);
-
- FW_ASSERT (("CyberStream sinks are read-only.", false));
- FW_Failure (FW_xWritableStream);
- }
-
- //-----------------------------------------------------------------------------
- // SLCySink::InitFromStream
- //-----------------------------------------------------------------------------
-
- SOM_Scope void SOMLINK SLCySink__InitFromStream(FW_OCyberSink *somSelf, Environment *ev,
- CyberStream* cs)
- {
- FW_UNUSED (ev);
-
- FW_OCyberSinkData *somThis = FW_OCyberSinkGetData(somSelf);
- somThis->fStream = cs;
- }
-
-